Add GtkGradient.
authorCarlos Garnacho <carlosg@gnome.org>
Thu, 2 Sep 2010 00:01:01 +0000 (02:01 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Sat, 4 Dec 2010 14:38:11 +0000 (15:38 +0100)
This type defines a gradient between 2 symbolic colors, with any number
of color stop between these. At the moment it has been put besides
GtkSymbolicColor, although should be completely private, it will likely
need extending in the future for radial gradients.

At some point, it maybe should also be used for images, so painting
both a gradient and an image is consistent.

gtk/gtkstyleset.h
gtk/gtksymboliccolor.c
gtk/gtksymboliccolor.h

index 8b8750c588530feb25097fcec9f24b290b59d28f..f81881a596f378a15325c86fc37cf0b4660c9c72 100644 (file)
@@ -106,6 +106,9 @@ void     gtk_style_set_merge          (GtkStyleSet       *set,
 gboolean gtk_symbolic_color_resolve (GtkSymbolicColor    *color,
                                     GtkStyleSet         *style_set,
                                      GdkColor            *resolved_color);
+gboolean gtk_gradient_resolve (GtkGradient      *gradient,
+                               GtkStyleSet      *style_set,
+                               cairo_pattern_t **resolved_gradient);
 
 G_END_DECLS
 
index 9b9386b4cd13c664b83212b2efbd0b882f787063..571021810220d4b2f726b41c1fa8a7c1209b9ab5 100644 (file)
@@ -22,6 +22,9 @@
 #include "gtkstyleset.h"
 #include "gtkintl.h"
 
+G_DEFINE_BOXED_TYPE (GtkGradient, gtk_gradient,
+                     gtk_gradient_ref, gtk_gradient_unref)
+
 /* Symbolic colors */
 typedef enum {
   COLOR_TYPE_LITERAL,
@@ -55,6 +58,26 @@ struct GtkSymbolicColor
   };
 };
 
+typedef struct ColorStop ColorStop;
+
+struct ColorStop
+{
+  gdouble offset;
+  GtkSymbolicColor *color;
+};
+
+struct GtkGradient
+{
+  gdouble x0;
+  gdouble y0;
+  gdouble x1;
+  gdouble y1;
+
+  GArray *stops;
+
+  guint ref_count;
+};
+
 GtkSymbolicColor *
 gtk_symbolic_color_new_literal (GdkColor *color)
 {
@@ -240,3 +263,112 @@ gtk_symbolic_color_get_type (void)
 
   return type;
 }
+
+/* GtkGradient */
+GtkGradient *
+gtk_gradient_new_linear (gdouble x0,
+                         gdouble y0,
+                         gdouble x1,
+                         gdouble y1)
+{
+  GtkGradient *gradient;
+
+  gradient = g_slice_new (GtkGradient);
+  gradient->stops = g_array_new (FALSE, FALSE, sizeof (ColorStop));
+
+  gradient->x0 = x0;
+  gradient->y0 = y0;
+  gradient->x1 = x1;
+  gradient->y1 = y1;
+
+  gradient->ref_count = 1;
+
+  return gradient;
+}
+
+void
+gtk_gradient_add_color_stop (GtkGradient      *gradient,
+                             gdouble           offset,
+                             GtkSymbolicColor *color)
+{
+  ColorStop stop;
+
+  g_return_if_fail (gradient != NULL);
+
+  stop.offset = offset;
+  stop.color = gtk_symbolic_color_ref (color);
+
+  g_array_append_val (gradient->stops, stop);
+}
+
+GtkGradient *
+gtk_gradient_ref (GtkGradient *gradient)
+{
+  g_return_val_if_fail (gradient != NULL, NULL);
+
+  gradient->ref_count++;
+
+  return gradient;
+}
+
+void
+gtk_gradient_unref (GtkGradient *gradient)
+{
+  g_return_if_fail (gradient != NULL);
+
+  gradient->ref_count--;
+
+  if (gradient->ref_count == 0)
+    {
+      guint i;
+
+      for (i = 0; i < gradient->stops->len; i++)
+        {
+          ColorStop *stop;
+
+          stop = &g_array_index (gradient->stops, ColorStop, i);
+          gtk_symbolic_color_unref (stop->color);
+        }
+
+      g_array_free (gradient->stops, TRUE);
+      g_slice_free (GtkGradient, gradient);
+    }
+}
+
+gboolean
+gtk_gradient_resolve (GtkGradient      *gradient,
+                      GtkStyleSet      *style_set,
+                      cairo_pattern_t **resolved_gradient)
+{
+  cairo_pattern_t *pattern;
+  guint i;
+
+  g_return_val_if_fail (gradient != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_STYLE_SET (style_set), FALSE);
+  g_return_val_if_fail (resolved_gradient != NULL, FALSE);
+
+  pattern = cairo_pattern_create_linear (gradient->x0, gradient->y0,
+                                         gradient->x1, gradient->y1);
+
+  for (i = 0; i < gradient->stops->len; i++)
+    {
+      ColorStop *stop;
+      GdkColor color;
+
+      stop = &g_array_index (gradient->stops, ColorStop, i);
+
+      if (!gtk_symbolic_color_resolve (stop->color, style_set, &color))
+        {
+          cairo_pattern_destroy (pattern);
+          return FALSE;
+        }
+
+      cairo_pattern_add_color_stop_rgb (pattern, stop->offset,
+                                        color.red / 65535.,
+                                        color.green / 65535.,
+                                        color.blue / 65535.);
+    }
+
+  *resolved_gradient = pattern;
+  return TRUE;
+}
index 8b3608bf217c5c9a26e7b8b7a1f26d5eff41d4b9..aedd2aa28edb311dfc37eb25bf10003a4b74439f 100644 (file)
@@ -26,11 +26,13 @@ G_BEGIN_DECLS
 
 /* Dummy typedefs */
 typedef struct GtkSymbolicColor GtkSymbolicColor;
-typedef struct GtkSymbolicColorMap GtkSymbolicColorMap;
+typedef struct GtkGradient GtkGradient;
 
 #define GTK_TYPE_SYMBOLIC_COLOR (gtk_symbolic_color_get_type ())
+#define GTK_TYPE_GRADIENT (gtk_gradient_get_type ())
 
 GType gtk_symbolic_color_get_type (void) G_GNUC_CONST;
+GType gtk_gradient_get_type (void) G_GNUC_CONST;
 
 GtkSymbolicColor * gtk_symbolic_color_new_literal (GdkColor         *color);
 GtkSymbolicColor * gtk_symbolic_color_new_name    (const gchar      *name);
@@ -43,6 +45,18 @@ GtkSymbolicColor * gtk_symbolic_color_new_mix     (GtkSymbolicColor *color1,
 GtkSymbolicColor * gtk_symbolic_color_ref   (GtkSymbolicColor *color);
 void               gtk_symbolic_color_unref (GtkSymbolicColor *color);
 
+GtkGradient * gtk_gradient_new_linear (gdouble x0,
+                                       gdouble y0,
+                                       gdouble x1,
+                                       gdouble y1);
+
+void gtk_gradient_add_color_stop (GtkGradient      *gradient,
+                                  gdouble           offset,
+                                  GtkSymbolicColor *color);
+
+GtkGradient * gtk_gradient_ref   (GtkGradient *gradient);
+void          gtk_gradient_unref (GtkGradient *gradient);
+
 G_END_DECLS
 
 #endif /* __GTK_SYMBOLIC_COLOR_H__ */